﻿using Nop.Core.Domain.Directory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nop.Core.Caching;
using Nop.Core.Data;
using Nop.Services.Events;

namespace Nop.Services.Directory
{
    public class RegionService : IRegionService
    {
        #region Constants
        private const string REGION_ALL_KEY = "Nop.region.all";
        private const string REGION_BY_ID_KEY = "Nop.region.id-{0}";
        private const string REGION_PATTERN_KEY = "Nop.region.";
        #endregion

        #region Fields

        private readonly IRepository<Region> _regionRepository;
        private readonly IEventPublisher _eventPublisher;
        private readonly ICacheManager _cacheManager;

        #endregion


         #region Ctor

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="cacheManager">Cache manager</param>
        /// <param name="regionRepository">Region repository</param>
        /// <param name="eventPublisher">Event published</param>
        public RegionService(ICacheManager cacheManager,
            IRepository<Region> regionRepository,
            IEventPublisher eventPublisher)
        {
            _cacheManager = cacheManager;
            _regionRepository = regionRepository;
            _eventPublisher = eventPublisher;
        }

        #endregion

        public ICollection<Region> GetAllRegions()
        {
            return _cacheManager.Get(REGION_ALL_KEY, () =>
            {
                var regions = _regionRepository.TableNoTracking.ToList();
                return regions;
            });
        }

        public Core.Domain.Directory.Region GetRegionById(int regionId)
        {
            if (regionId < 1)
            {
                return null;
            }

            var key = string.Format(REGION_BY_ID_KEY, regionId);
            return _cacheManager.Get(key, () =>
            {
                var region = _regionRepository.GetById(regionId);
                return region;
            });
        }

        public Region GetRegionByName(string regionName)
        {
            if (string.IsNullOrWhiteSpace(regionName))
                return null;

            return
                _regionRepository.Table.FirstOrDefault(r => r.Name.Equals(regionName, StringComparison.OrdinalIgnoreCase));
        }

        public void InsertRegion(Core.Domain.Directory.Region region)
        {
            if (region == null)
                throw new ArgumentNullException("region");

            _regionRepository.Insert(region);

            _cacheManager.RemoveByPattern(REGION_PATTERN_KEY);

            _eventPublisher.EntityInserted(region);
        }

        public void UpdateRegion(Core.Domain.Directory.Region region)
        {
            if (region == null)
                throw new ArgumentNullException("region");

            _regionRepository.Update(region);

            _cacheManager.RemoveByPattern(REGION_PATTERN_KEY);

            _eventPublisher.EntityUpdated(region);
        }
    }
}
